package com.zhanglijie.improve.aqs.mix.stampedLock;

import java.lang.reflect.Field;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.StampedLock;

import org.omg.SendingContext.RunTime;

import sun.misc.Unsafe;

/**
 * @author zhanglijie
 * @version 1.0
 * @since 1.1.0 2022/10/30 0030 16:35
 * 注意 读写节点枪锁机会是一半一半的 写-》读一堆-》写。。。
 */
public class MyStampedLock {



    /**
     * 节点类
     */
    static class WNode{
        volatile WNode prev;
        volatile WNode next;
        volatile WNode cowait;
        volatile Thread thread;
        volatile int status;
        int mode;
        public WNode(int mode,WNode p){
            this.mode = mode;
            this.prev = p;
        }
    }

    private volatile WNode whead;
    private volatile WNode wtail;

    private ReadLockView readLockView;
    private WriteLockView writeLockView;

    private volatile long state;
    private int readerOverflow;
    private static final int OVERFLOW_YEILD_RATE = 7;
    private static final int LG_READERS = 7;
    private static final long WBIT = 1<<LG_READERS;// 1000 0000 128
    private static final long ORIGIN = WBIT<<1; // 1 0000 0000 256
    private static final long RBITS = WBIT-1;//127
    private static final long ABITS = RBITS|WBIT;//1111 1111 (255)= 0111 1111 | 1000 1111
    private static final long RFULL = RBITS-1;//0111 1110=126
    private static final long RUNIT = 1;//读锁的一个单位
    private static final int NCPU = Runtime.getRuntime().availableProcessors();
    private static final int SPINS = (NCPU > 1)?1<<6:0;//多核64自旋次数 否则0
    private static final int HEAD_SPINS = (NCPU>1)?1<<10:0;//多核cpu默认自旋1024
    private static final int MAX_HEAD_SPINS = (NCPU>1)?1<<16:0;//65536
    private static final int RMODE = 0;//读模式--读线程
    private static final int WMODE = 1;//写模式--写线程（头节点默认是写类型）
    private static final int WAITING = -1;//表示后继节点即将阻塞或者已经阻塞
    private static final int CANCELL = 1;//表示本节点取消状态
    private static final long SBITS = ~RBITS;
    private static final long INTERRUPTED = 1L;
    public MyStampedLock(){

    }

    public static void main(String[] args) {
        System.out.println(ABITS);
    }

    class ReadLockView implements Lock {
        /**
         * 读锁加锁
         */
        @Override
        public void lock() {
            readLock();
        }

        @Override
        public void lockInterruptibly() throws InterruptedException {

        }

        @Override
        public boolean tryLock() {
            return false;
        }

        @Override
        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
            return false;
        }

        /**
         * 读锁解锁
         */
        @Override
        public void unlock() {
            unstampedUnLockRead();
        }

        @Override
        public Condition newCondition() {
            return null;
        }
    }

    private void unstampedUnLockRead() {
        for (;;) {
            long s, m;  WNode h;
            //没锁或者有写锁是不能释放读锁的
            if ((m = (s = state) & ABITS) == 0L || m >= WBIT) {
                throw new IllegalMonitorStateException();
            }
            else if (m < RFULL) {
                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
                    if (m == RUNIT && (h = whead) != null && h.status != 0) {
                        release(h);//唤醒后继节点 当只剩下一个（最后一个读线程）
                    }
                    break;
                }
            }
            else if (tryDecReaderOverflow(s) != 0L) {
                break;
            }
        }
    }

    private void release(WNode h) {
        if (h != null) {
            WNode q; Thread w;
            U.compareAndSwapInt(h, WSTATUS, WAITING, 0);
            if ((q = h.next) == null || q.status == CANCELL) {
                for (WNode t = wtail; t != null && t != h; t = t.prev) {
                    if (t.status <= 0) {
                        q = t;
                    }
                }
            }
            if (q != null && (w = q.thread) != null) {
                U.unpark(w);
            }
        }
    }

    private long tryDecReaderOverflow(long s) {

        if ((s & ABITS) == RFULL) {//1.正好==RFRLL 2.readerOverflow+RFULL
            if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
                int r; long next;
                if ((r = readerOverflow) > 0) {
                    readerOverflow = r - 1;
                    next = s;
                }
                else {
                    next = s - RUNIT;
                }
                state = next;
                return next;
            }
        }
        else if ((MyLockSupport.nextSecondarySeed() & OVERFLOW_YEILD_RATE) == 0) {
            Thread.yield();
        }
        return 0L;//返回0表示此次释放失败
    }
    private void unstampedUnLockWrite() {
        WNode h; long s;
        if (((s = state) & WBIT) == 0L) {
            throw new IllegalMonitorStateException();
        }
        state = (s += WBIT) == 0L ? ORIGIN : s;
        if ((h = whead) != null && h.status != 0) {
            release(h);
        }
    }

    private long readLock() {
        //能够获取读锁的条件：没有线程和获取到写锁，读锁未超限

        long s = STATE, next;
        return (whead == wtail)//whead == wtail 如果null 表示还没形成阻塞队列 如果相同就是阻塞队列就一个head节点 可以进行读
            && (s & ABITS) < RFULL && U.compareAndSwapLong(this, STATE, s, next = s + RUNIT) ?
            next : acquireRead(false, 0);
    }

    /**
     * 读锁自旋阻塞获取锁
     * @param interruptbiliy
     * @param deadline
     * @return
     */
    private long acquireRead(boolean interruptbiliy, int deadline) {
      //第一个大循环：自旋入队
        WNode node = null,p;//node标记即将入队的节点，p表示指向入队之前尾节点的指针
        for(int spins =-1;;){
            //符合条件的则自旋
            WNode h;
            //表示队列为空或者队列里面只有一个头节点（此头节点有可能正在执行也有可能执行完了灭有后继了会放在这里占位）， 此时表示有资格自旋（因为下一个获取锁的线程就是自己）
            if((h=whead) == (p=wtail)) {
                for (long m, s, ns; ; ) {
                    //RFULL 126 碰到头节点是读可以无限制自旋抢
                    if ((m = (s = state) & ABITS) < RFULL ? U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
                        (m < WBIT && (ns = tryIncReaderOverFlow(s)) != 0)) {//WBIT=128  所以m有可能是126或者127(127可能在递增时候被挡调了）
                        return ns;
                    }
                    //此时有其他线程拿到了写锁，因此需要开始自旋等待别人释放写锁-自旋64
                    //此时会执行下面自旋代码 自旋64次
                    else if (m >= WBIT) {
                        if (spins > 0) {
                            if (MyLockSupport.nextSecondarySeed() >= 0) {
                                --spins;//如果生产随机数>=0 才算一次有效自旋
                            }
                        } else {//spins<=0
                            //自旋次数减到0了，自旋结束
                            if (spins == 0) {
                                WNode nh = whead, np = wtail;
                                //如果此时写锁还没释放 || 头尾节点不相等（有人插进来了）
                                if ((nh == h && np == p) || (h = nh) != (p = np)) {
                                    //因为自旋次数到了 写锁没有释放|| 有节点进来了
                                    break;
                                }
                            }
                            spins = SPINS;
                        }
                    }
                }
            }
            //到阻塞前都是入队

                //自旋（只有个写锁线程占着）或者读线程cas失败 则入队
                if(p == null){//阻塞队列还没初始化,初始化队列要把null的头节点也要创建起来 本节点成为空内容头节点的后继节点
                    //头节点默认是写类型，因为读类型可以并行执行 写类型后面的节点会等待 等写类型执行完唤醒后继连串的读类型节点
                    WNode hd = new WNode(WMODE, null);//这个程序中只有写线程在执行没有其他线程 读线程自旋失败入队 此时队列位空
                    if(U.compareAndSwapObject(this,WHEAD,null,hd)){
                        wtail = hd;
                    }
                }
                //创建自身节点,可能是创建头节点的那个线程 也可能是没自旋抢到锁的线程
                else if(node == null){
                    node = new WNode(RMODE,p);
                }
                //创建完入队
                //如果此时队列只有一个头节点但是上面自旋没抢到只能入队 （ 或者尾节点是写节点-读写互斥的必须入队不能自旋了，如果是读节点可以通过入栈解决不用入队哦！！）
                else if(h == p || p.mode !=RMODE){
                    if(node.prev != p){
                        node.prev = p;
                    }
                    else if(U.compareAndSwapObject(this,WTAIL,p,node)){
                        p.next = node;
                        break;//这种情况入队后break
                    }
                }
                //以下是入栈逻辑(也就是说p是读线程节点 p-尾节点 && 当前存在队列不止一个节点了）
                else if(!U.compareAndSwapObject(p,WCOWAIT,node.cowait=p.cowait,node)){
                     node.cowait = null;//失败还原一下node.cowait=p.cowait
                 }
                 //栈上节点自旋或者阻塞(走到这里说明已经入栈逻辑成功了）==栈上的线程都可以干下面自旋阻塞逻辑，而不对于   else if(h == p || p.mode !=RMODE)
                else{
                     for(;;) {

                         WNode pp,c;Thread currentThread;
                         //唤醒的栈的节点协助唤醒
                         if ((h = whead) != null && (c = h.cowait) != null &&
                             U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
                             (currentThread = c.thread) != null) // help release
                             U.unpark(currentThread);
                         //p为头节点或者第二个节点或者队列为空 就可以自旋
                         if (h == (pp = p.prev) || h == p || pp == null){
                            long m,s,ns;
                             do{
                                 if ((m = (s = state) & ABITS) < RFULL ? U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
                                     (m < WBIT && (ns = tryIncReaderOverFlow(s)) != 0)){
                                     return ns;
                                 }
                             }while(m<WBIT);
                         }

                         //自旋条件不满足(有写线程占据锁） 那么阻塞
                         //走到这里头节点和pp节点(p节点也没有变化)都没有变化 那么栈上的读线程就会阻塞
                         if(whead == h && p.prev == pp){
                             long time;
                             //队列只有一个节点了 或者那个只有一个节点的是取消状态了
                             if(pp == null || h==p || p.status >0){
                                 //我可以执行了 不用放到队列中 break去执行业务代码
                                 node = null;
                                 break;
                             }
                             if(deadline == 0){
                                 time = 0;
                             }
                             //时间到了 不等了取消本线程
                             else if((time = deadline-System.nanoTime()) <= 0){
                                 return cancleWaiter(node,node,false);//这个todo cancleWaiter(node,p,true)
                             }
                             currentThread = Thread.currentThread();
                             U.putObject(currentThread,PARKBLOCKER,this);
                             node.thread = currentThread;

                             if((pp != h || (state&ABITS) == WBIT) &&
                                 whead == h && p.prev == pp){
                                 U.park(false,time);
                             }
                             //走到这里就被唤醒了||之前没资格阻塞==下面还原清除
                             node.thread = null;
                             U.putObject(currentThread,PARKBLOCKER,null);
                             //是否相应中断,如果能中断取消
                             if(interruptbiliy && Thread.interrupted()){
                                 return cancleWaiter(node,p,true);
                             }
                         }
                     }

                }

        }
        //不针对入栈的阻塞
        for(int spins = -1;;){
           WNode h,np,pp;int ps;
           //为啥不用wtail 而是用p 因为这个阻塞前p代表离本node最近的尾节点 如果p成为头说明本node有机会枪锁了 head->node这个情形
           //如果 head-p-node说明node更有机会了 更应该node去枪锁了
            if((h=whead) == p){
               if(spins < 0){
                   spins = HEAD_SPINS;
               }else if(spins < MAX_HEAD_SPINS){
                   spins<<=1;//扩大一倍
               }
               for(int k=spins;;){
                   long m,s,ns;
                   if ((m = (s = state) & ABITS) < RFULL ? U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
                       (m < WBIT && (ns = tryIncReaderOverFlow(s)) != 0)) {//WBIT=128  所以s有可能是126或者127(127可能在递增时候被挡调了）//todo
                       //抢到锁 挪动队列指针
                       WNode c;Thread w;
                       whead = node;
                       node.prev = null;
                       //继续唤醒后继节点
                       while((c = node.cowait) != null){
                           if(U.compareAndSwapObject(node,WCOWAIT,c,c.cowait) && (w = c.thread) != null){
                               U.unpark(w);
                           }
                       }
                       return ns;
                   }
                   //这里才是真正的最后的自旋减一操作
                   //此时有写锁，并且自旋次数用完了 只能从头再来一次 spins下一轮扩大一倍因为spins此时==0
                   else if(m >= WBIT && MyLockSupport.nextSecondarySeed() >= 0 && --k <= 0) {
                       break;
                   }
               }
           }  else if (h != null) {//读加入队列后阻塞前可以协助是否能做正在唤醒的栈的节点唤醒
                WNode c; Thread w;
                while ((c = h.cowait) != null) {
                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) && (w = c.thread) != null) {
                        U.unpark(w);
                    }
                }
            }
            // 走到这里表示第一轮自旋失败
            //阻塞步骤：1、前驱节点状态改位-1  2、执行阻塞
            if(whead == h){//头节点还没变  todo(thread&&为啥是head没有变动）==如果head动了说明自己可以自旋获得 通过循环自旋完成。thread没赋值倒是自己抢锁成功了 之前入队的thread=null的节点咋办
                if((np=node.prev) != p){//由于会出现取消节点状态 node.prev是动态变化的，这是每轮第一次因此需要重置node.prev==p。将真实的当前线程为节点归真处理
                    if(np != null){
                        (p=np).next = node;
                    }
                }
                //修改前驱节点状态为-1
                else if((ps=p.status) == 0){
                    U.compareAndSwapInt(p,WSTATUS,0,WAITING);
                }
                //如果前驱是取消状态 直接踢出
                else if(ps == CANCELL){
                    if((pp=p.prev) != null){
                        node.prev = pp;
                        pp.next = node;
                    }
                }
                //真正阻塞
                else{
                    long time;
                    if(deadline == 0){
                        time = 0;
                    }
                    //时间到了 不等了取消本线程
                    else if((time = deadline-System.nanoTime()) <= 0){
                        return cancleWaiter(node,node,false);
                    }
                    Thread currentThread = Thread.currentThread();
                    U.putObject(currentThread,PARKBLOCKER,this);
                    node.thread = currentThread;
                    //前驱节点状态为等待状态（表示后继可以阻塞，后继也就是本节点状态存储在前驱节点status中）
                    //中间有其他节点，自己不是第二个节点 或者 写锁被占用
                    //头尾节点没动（说明没节点被唤醒） 如果动了她说可以再次循环自旋一次试试
                    if(p.status < 0 && (p != h || (state&ABITS) == WBIT) &&
                    whead == h && node.prev == p){
                        U.park(false,time);
                    }
                    //走到这里就被唤醒了||之前没资格阻塞==下面还原清除
                    node.thread = null;
                    U.putObject(currentThread,PARKBLOCKER,null);
                    //是否相应中断,如果能中断取消
                    if(interruptbiliy && Thread.interrupted()){
                        return cancleWaiter(node,node,false);
                    }
                }
            }
        }
    }

    /**
     * 取消等待
     * @param node
     * @param group
     * @param interrupted
     * @return
     */
    private long cancleWaiter(WNode node, WNode group, boolean interrupted) {
        if (node != null && group != null) {
            Thread w;
            //当前节点置为取消状态
            node.status = CANCELL;
            //将栈上取消状态踢出
            for (WNode p = group, q; (q = p.cowait) != null;) {
                if (q.status == CANCELL) {
                    U.compareAndSwapObject(p, WCOWAIT, q, q.cowait);
                    p = group; // restart
                }
                else {
                    p = q;
                }
            }
            //取消的节点是栈顶节点（1.栈顶  2.队列上）  node后面的pre没有动  node前面的pre动了为什么？ 这个和唤醒流程有关 // wake up succ to observe new pred
            if (group == node) {
                //唤醒栈上所有线程节点
                for ( WNode r = group.cowait; r != null; r = r.cowait) {
                    if ((w = r.thread) != null) {
                        U.unpark(w);
                    }
                }
                //队列上处理
                for ( WNode pred = node.prev; pred != null; ) { // unsplice
                    WNode succ, pp;        // find valid successor
                    //处理node及其之后的取消节点
                    //处理后继是null(node就是tail)则将node移除  || 处理node到tail存在cancel节点时候，则移除node-->notCancelNode
                    while ((succ = node.next) == null || succ.status == CANCELL) {
                        WNode q = null;    // find successor the slow way
                        for (WNode t = wtail; t != null && t != node; t = t.prev) {
                            if (t.status != CANCELL) {
                                q = t;
                            }
                        }
                        if (succ == q || U.compareAndSwapObject(node, WNEXT, succ, succ = q)) {
                            if (succ == null && node == wtail) {
                                U.compareAndSwapObject(this, WTAIL, node, pred);
                            }
                            break;
                        }
                    }
                    //处理node前面的节点
                    //移除node本身 将pre.next = nextValidNode
                    if (pred.next == node) {
                        U.compareAndSwapObject(pred, WNEXT, node, succ);
                    }
                    if (succ != null && (w = succ.thread) != null) {
                        succ.thread = null;
                        U.unpark(w);       // wake up succ to observe new pred
                    }
                    //完事大吉  pre状态合法  pre是头节点
                    if (pred.status != CANCELL || (pp = pred.prev) == null) {
                        break;
                    }
                    //pre状态不合法 踢出
                    node.prev = pp;        // repeat if new pred wrong/cancelled
                    U.compareAndSwapObject(pp, WNEXT, pred, succ);
                    //往前递归处理
                    pred = pp;
                }
            }
        }

        WNode h;
        while ((h = whead) != null) {
            long s; WNode q; // similar to release() but check eligibility
            if ((q = h.next) == null || q.status == CANCELL) {//找到head后面第一个有效节点
                for (WNode t = wtail; t != null && t != h; t = t.prev) {
                    if (t.status <= 0) {
                        q = t;
                    }
                }
            }
            if (h == whead) {//如果这个有效节点是读 && 当前是读线程占有锁 唤醒这个有效节点 提升效率
                if (q != null && h.status == 0 && ((s = state) & ABITS) != WBIT && (s == 0L || q.mode == RMODE)) {
                    release(h);
                }
                break;
            }
        }
        return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
    }

    /**
     * 读锁数量最高给126.如果达到127 做overflow操作
     * @param s
     * @return
     */
    private long tryIncReaderOverFlow(long s) {
        //读锁数量已经到阈值126了
        if((s&ABITS) == RFULL){
            if(U.compareAndSwapLong(this,STATE,s,s|RBITS)){// RBIT=127   s|RBITS=127
                ++readerOverflow;
                state=s;//这里还原成126
                return s;
            }
        }
        //否则下面以随机的概率主动放弃cpu执行权（有人释放了锁或者127情况下（因为最大126 127是不可能出现的 要么》=128有写锁占据情况））
        //走到这里表示之前读锁是满的 然后进入到这个方法之后呢读锁又不满了 说明之前有线程释放了读锁
        //所以这个地方会再让线程等一会 然后在重新尝试

        if((MyLockSupport.nextSecondarySeed() & OVERFLOW_YEILD_RATE) == 0){
            Thread.yield();
        }
        return 0;
    }

    class WriteLockView implements Lock{

        /**
         * 写锁加锁
         */
        @Override
        public void lock() {
            writeLock();
        }

        @Override
        public void lockInterruptibly() throws InterruptedException {

        }

        @Override
        public boolean tryLock() {
            return false;
        }

        @Override
        public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
            return false;
        }

        /**
         * 写锁解锁
         */
        @Override
        public void unlock() {
            unstampedUnLockWrite();
        }

        @Override
        public Condition newCondition() {
            return null;
        }
    }

    /**
     * 转换为写锁（前提是同一个线程 老的锁获得线程等于新获得锁的线程）
     * @param stamp
     * @return
     */
    public long tryConvertToWriteLock(long stamp){
        long a = stamp & ABITS, m, s, next;//ABITS=255 *****11111111
        while (((s = state) & SBITS) == (stamp & SBITS)) {//SBITS=~RBIT(*******1111111)
            //无锁
            if ((m = s & ABITS) == 0L) {
                if (a != 0L)
                    break;
                if (U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
                    return next;
            }
            //有写锁
            else if (m == WBIT) {
                if (a != m)
                    break;
                return stamp;
            }
            //只有一个读锁
            else if (m == RUNIT && a != 0L) {
                //先释放读锁 再获得写锁
                if (U.compareAndSwapLong(this, STATE, s, next = s - RUNIT + WBIT))
                    return next;
            }
            else
                break;
        }
        return 0L;

    }

    /**
     * 转换为读锁
     * @param stamp
     * @return
     */
    public long tryConvertToReadLock(long stamp) {
        long a = stamp & ABITS, m, s, next;  WNode h;
        while (((s = state) & SBITS) == (stamp & SBITS)) {
            //无锁状态
            if ((m = s & ABITS) == 0L) {
                //已经无锁了 但是你给的stamp不是0 所以直接break
                if (a != 0L)
                    break;
                //无锁情况+读锁
                else if (m < RFULL) {
                    if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
                        return next;
                }
                //可能由于别的竞争时候导致读锁再611-620代码间满了
                else if ((next = tryIncReaderOverFlow(s)) != 0L)
                    return next;
            }
            //本身写锁
            else if (m == WBIT) {
                if (a != m)
                    break;
                state = next = s + (WBIT + RUNIT);
                if ((h = whead) != null && h.status != 0)
                    release(h);
                return next;
            }
            //本身占有读锁
            else if (a != 0L && a < WBIT)
                return stamp;
            else
                break;
        }
        return 0L;
    }


    public long tryConvertToOptimisticRead(long stamp) {
        long a = stamp & ABITS, m, s, next; WNode h;
        U.loadFence();//刷新内存
        for (;;) {
            if (((s = state) & SBITS) != (stamp & SBITS))
                break;
            //本身就是乐观锁 或者无锁（无锁也是一种乐观锁 只不过版本号0）
            if ((m = s & ABITS) == 0L) {
                if (a != 0L)
                    break;
                return s;
            }
            //写锁
            else if (m == WBIT) {
                if (a != m)
                    break;
                state = next = (s += WBIT) == 0L ? ORIGIN : s;
                if ((h = whead) != null && h.status != 0)
                    release(h);
                return next;
            }
            //走到这里当前m只能是读锁 所以a>=WBIT不会出现
            //a==0 表示老版本本身无锁，return 0  a》=wbit这里非法  因为到这里只有读锁情况了
            else if (a == 0L || a >= WBIT)
                break;
            //读锁
            else if (m < RFULL) {
                if (U.compareAndSwapLong(this, STATE, s, next = s - RUNIT)) {
                    if (m == RUNIT && (h = whead) != null && h.status != 0)
                        release(h);
                    return next & SBITS;
                }
            }
            else if ((next = tryDecReaderOverflow(s)) != 0L)
                return next & SBITS;//版本号
        }
        return 0L;
    }

    /**
     * 写锁获取锁
     * @return
     */
    private long writeLock() {
        //state+1个单位的写锁=state+1000 0000
        long s,next;
        //加写锁的条件是什么？ 0000 0000全是零才能加写锁
        return ((s=state)&ABITS) == 0 && U.compareAndSwapLong(this,STATE,s,next = s+WBIT)?
            next:acquireWrite(false,0);
    }

    private long acquireWrite(boolean interruptbily, int deadline) {
        WNode node = null, p;
        //自旋入队逻辑
        for (int spins = -1;;) { // spin while enqueuing
            long m, s, ns;
            if ((m = (s = state) & ABITS) == 0L) {//没人持有读写锁 可以cas尝试
                if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT)) {
                    return ns;
                }
            }
            else if (spins < 0) {
                //只有头节点并且写锁被占有 自旋赋值
                spins = (m == WBIT && wtail == whead) ? SPINS : 0;
            }
            else if (spins > 0) {
                //自旋一次计数-1
                if (MyLockSupport.nextSecondarySeed() >= 0) {
                    --spins;
                }
            }
            else if ((p = wtail) == null) { //初始化队列
                WNode hd = new WNode(WMODE, null);
                if (U.compareAndSwapObject(this, WHEAD, null, hd)) {
                    wtail = hd;
                }
            }
            else if (node == null) {//创建节点
                node = new WNode(WMODE, p);
            }
            //下面两个入队 成功后break
            else if (node.prev != p) {//这个是防止中途p被cancel了
                node.prev = p;
            }
            else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
                p.next = node;
                break;
            }
        }

        //自旋阻塞逻辑
        for (int spins = -1;;) {
            WNode h, np, pp; int ps;
            //自旋cas 因为head->node
            if ((h = whead) == p) {
                if (spins < 0) {
                    spins = HEAD_SPINS;
                }
                else if (spins < MAX_HEAD_SPINS) {
                    spins <<= 1;
                }
                for (int k = spins;;) { // spin at head
                    long s, ns;
                    if (((s = state) & ABITS) == 0L) {
                        if (U.compareAndSwapLong(this, STATE, s,
                            ns = s + WBIT)) {
                            whead = node;
                            node.prev = null;
                            return ns;
                        }
                    }
                    else if (MyLockSupport.nextSecondarySeed() >= 0 && --k <= 0) {
                        break;
                    }
                }
            }

            else if (h != null) { // //写加入队列后阻塞前可以协助是否能做正在唤醒的栈的节点唤醒
                WNode c; Thread w;
                while ((c = h.cowait) != null) {
                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) && (w = c.thread) != null) {
                        U.unpark(w);
                    }
                }
            }
            //下面就得阻塞了 因为head->pre->node
            if (whead == h) {
                //归真前驱由于可能取消的操作
                if ((np = node.prev) != p) {
                    if (np != null) {
                        (p = np).next = node;
                    }
                }
                //前驱状态该wait
                else if ((ps = p.status) == 0) {
                    U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
                }
                else if (ps == CANCELL) {//踢出取消状态
                    if ((pp = p.prev) != null) {
                        node.prev = pp;
                        pp.next = node;
                    }
                }
                else {
                    long time; // 0 argument to park means no timeout
                    if (deadline == 0L) {
                        time = 0L;
                    }
                    else if ((time = deadline - System.nanoTime()) <= 0L) {
                        return cancleWaiter(node, node, false);
                    }
                    Thread wt = Thread.currentThread();
                    U.putObject(wt, PARKBLOCKER, this);
                    node.thread = wt;
                    //有两个节点 || 有读写操作占据锁
                    if (p.status < 0 && (p != h || (state & ABITS) != 0L) && whead == h && node.prev == p) {
                        U.park(false, time);  // emulate MyLockSupport.park
                    }
                    node.thread = null;
                    U.putObject(wt, PARKBLOCKER, null);
                    if (interruptbily && Thread.interrupted()) {
                        return cancleWaiter(node, node, true);
                    }
                }
            }
        }
    }

    // Unsafe mechanics
    private static final Unsafe U;
    private static final long STATE;
    private static final long WHEAD;
    private static final long WTAIL;
    private static final long WNEXT;
    private static final long WSTATUS;
    private static final long WCOWAIT;
    private static final long PARKBLOCKER;

    static {
        try {
            U = getUnsafe();
            Class<?> k =MyStampedLock.class;
            Class<?> wk = WNode.class;
            STATE = U.objectFieldOffset
                (k.getDeclaredField("state"));
            WHEAD = U.objectFieldOffset
                (k.getDeclaredField("whead"));
            WTAIL = U.objectFieldOffset
                (k.getDeclaredField("wtail"));
            WSTATUS = U.objectFieldOffset
                (wk.getDeclaredField("status"));
            WNEXT = U.objectFieldOffset
                (wk.getDeclaredField("next"));
            WCOWAIT = U.objectFieldOffset
                (wk.getDeclaredField("cowait"));
            Class<?> tk = Thread.class;
            PARKBLOCKER = U.objectFieldOffset
                (tk.getDeclaredField("parkBlocker"));

        } catch (Exception e) {
            throw new Error(e);
        }
    }


    private static Unsafe getUnsafe(){

        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            Unsafe obj = (Unsafe) theUnsafe.get(null);//静态变量给个null 实例变量给当前实例对象
            return obj ;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }


}
